const {menu, ccclass} = cc._decorator;

//链式参数
export interface PlayAnimationThen {
    //执行
    start: (loop: boolean) => PlayAnimationThen;
    //完成回调
    onComplete: (
        callCount: number,
        callFunc: () => void
    ) => PlayAnimationThen,
    //帧事件回调
    onEvent: (
        callCount: number,
        callFunc: (trackEntry: sp.spine.TrackEntry, event: sp.spine.Event) => void
    ) => PlayAnimationThen;
}

@ccclass
@menu('框架组件/骨骼动画')
export default class comSpSkeleton extends sp.Skeleton {

    constructor() {
        super();
    }

    //回调监听次数
    private m_completeCount: number = 0;
    //回调函数
    private m_completeCallback: () => void = null;
    //事件回调
    private m_trackEntryEventCallback: (trackEntry: sp.spine.TrackEntry, event: sp.spine.Event) => void = null;
    //事件回调监听几欠
    private m_trackEventCount: number = 0;
    //当前皮肤
    private m_currSkinName: string = null;

    protected start() {
        this.m_currSkinName = this.defaultSkin;
    }

    /**
     * 播放动画
     * @param animationName 动画名称
     */
    playAnimation(animationName: string): PlayAnimationThen {
        this.m_completeCount = 0;
        this.m_completeCallback = null;
        this.m_trackEventCount = 0;
        this.m_trackEntryEventCallback = null;
        //
        let then: PlayAnimationThen = {
            onComplete: (callCount, callFunc) => {
                this.m_completeCount = callCount;
                this.m_completeCallback = callFunc;
                return then;
            },
            onEvent: (callCount, callFunc) => {
                this.m_trackEventCount = callCount;
                this.m_trackEntryEventCallback = callFunc;
                return then;
            },
            start: (loop) => {
                //先监听回调
                this.setCompleteListener(this.onPlayAnimationOver.bind(this));
                //
                let track = this.setAnimation(0, animationName, loop);
                //事件监听
                this.setEventListener(this.onPlayEvent.bind(this));
                // this.setTrackEventListener(track, this.onPlayEvent.bind(this));
                //
                return then;
            },
        };

        //
        return then;
    }

    getCurrAnimation(): sp.spine.Animation {
        return this.getCurrent(0).animation;
    }

    //获取当前动作需要时间
    getCurrAnimationEndTime(): number {
        if (this.getCurrAnimation()) {
            return this.getCurrAnimation().duration;
        }
    }

    //获取当前动作名称
    getCurrAnimationName(): string {
        if (this.getCurrAnimation()) {
            return this.getCurrAnimation().name;
        }
    }

    //获取当前播放时间
    getCurrAnimationPlayTime(): number {
        return this.getCurrent(0).trackTime;
    }

    //设置当前播放时间
    setCurrAnimationPlayTime(time: number) {
        this.getCurrent(0).trackTime = time;
    }

    /**
     * 切换插槽附件
     * @param srcSlotName 源插槽
     * @param deskSlotName 目标插槽
     * @param srcSkeleton 源骨骼 默认为自身
     * @param srcSkin 源皮肤 默认为空 srcSkeleton与srcSkin不能同时缺省
     */
    replaceTheSlot(srcSlotName: string, deskSlotName: string, srcSkeleton?: comSpSkeleton, srcSkin?: string) {
        if (!srcSkeleton && !srcSkin) {
            console.error('#1171033 参数3、4不能同时为空');
            return;
        }
        let src = srcSkeleton || this;
        let meSlot = this.findSlot(deskSlotName);
        //
        let lastSrcSkin = src.getCurrSkinName();
        //
        if (srcSkin) {
            src.setSkin(srcSkin);
        }
        //
        let srcSlot = src.findSlot(srcSlotName);
        let srcAttachment = srcSlot.getAttachment();
        //
        src.setSkin(lastSrcSkin);
        meSlot.setAttachment(srcAttachment);
    }

    setSkin(skinName: string): void {
        super.setSkin(skinName);
        this.m_currSkinName = skinName;
    }

    getCurrSkinName() {
        return this.m_currSkinName;
    }

    private onPlayAnimationOver() {
        //有回调并且还有次数
        if (this.m_completeCallback && this.m_completeCount != 0) {
            this.m_completeCallback();
            this.m_completeCount--;
        }
        //事件回调也在播放一次时计数
        if (this.m_trackEntryEventCallback && this.m_trackEventCount != 0) {
            this.m_trackEventCount--;
        }
    }

    private onPlayEvent(trackEntry: sp.spine.TrackEntry, event: sp.spine.Event) {
        //
        if (this.m_trackEntryEventCallback && this.m_trackEventCount != 0) {
            this.m_trackEntryEventCallback(trackEntry, event);
        }
    }
}